


import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Locale;
import java.util.Random;



import pluginUtils.Circle;
import pluginUtils.CircleArrangement;
import pluginUtils.Complexe;
import pluginUtils.DoyleCircle;
import pluginUtils.MobiusTransform;

import pluginUtils.PackCircle;


public class Amish extends ImagePlus implements PlugIn{
        {Locale.setDefault(Locale.US); }
       
        private ImageProcessor primeIP;
        private int X=2000,Y=2000; // image size
       
        private PrintStream output,blenderOutput;
        private double xShift=0;
        private double zShift=0;
       
       

        private Random generator=new Random(); // One always needs some randomness
       
        // For the scaling of the image
        private double x0=0,x1=1,y0=0,y1=1;
        private double acoef,ccoef,vcoef,wcoef;
       
        private String[] palette={"Yellow","Red","Blue","Green","White","NavyBlue","Turquoise","Orange"};
        private Color[] palette1={Color.YELLOW,Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA,Color.ORANGE};
        public void setCoefs(){
                acoef=X/(x1-x0);
                vcoef=Y/(y1-y0);
                ccoef=-acoef*x0;
                wcoef=-vcoef*y0;
        }
         
       
       
        public void setBounds(double xl,double xu,double yl,double yu){
                x0=xl;
                x1=xu;
                y0=yl;
                y1=yu;
        }
       
        private void drawCircle(PackCircle c){
                //if(intersect(c))return;
               
                //if(c.getRadius()<0.1) return;
                int intX=(int)(c.getX()*acoef+ccoef);
                int intY=(int)(c.getY()*vcoef+wcoef);
                int intRx=(int)(c.getRadius()*acoef);
                int intRy=(int)(c.getRadius()*vcoef);
                int rank=((int)(c.getCouleur()*60))%6;
       
                       
                        double Xs=c.getX();
                        double Ys=c.getY();
                        double rapp=Xs*Xs+Ys*Ys+1;
                        double u=Xs/rapp;
                        double v=Ys/rapp;
                        double w=(Xs*Xs+Ys*Ys)/rapp;
                       
                        double Xsr=c.getX();
                        double Ysr=c.getY()+c.getRadius();
                        double rappr=Xsr*Xsr+Ysr*Ysr+1;
                        double ur=Xsr/rappr;
                        double vr=Ysr/rappr;
                        double wr=(Xsr*Xsr+Ysr*Ysr)/rappr;
               
                        double nrad=(u-ur)*(u-ur)+(v-vr)*(v-vr)+(w-wr)*(w-wr);
                        //nrad=Math.sqrt(nrad)*1.414;
                       
                        String s="sphere{<"+u+","+v+","+w+">,";
                       
                       
                        s+=nrad;
                        s+=" texture{Texture"+rank+"} finish{Finish"+rank+"}}";
                        output.println(s);
               
        }
               
       
        private void drawColoredCircle(PackCircle c){
                double xCenter=c.getX();
                double yCenter=c.getY();
                //if(c.getRadius()<0.001) return ;
               
                int intX=(int)((xCenter-xShift)*acoef+ccoef);
                int intY=(int)((yCenter-zShift)*vcoef+wcoef);
                int intRx=(int)(c.getRadius()*acoef);
                int intRy=(int)(c.getRadius()*vcoef);
               
               
                primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
               
                /*
                primeIP.moveTo(intX,intY);
                primeIP.drawString(c.getMyOrder()+"");
                */
               
                String s="sphere{<"+xCenter+",0,"+yCenter+">,";
                s+=c.getRadius();
                s+=" texture{pigment{color White}} finish{reflection 0.2}}";
                System.out.println(s);
                output.println(s);
       
        }
       
        private void drawCircle(Circle c,double rot){
                double xCenter=c.getCenter().getReal();
                double yCenter=c.getCenter().getIm();
                //if(c.getRadius()<0.001) return ;
               
                int intX=(int)((xCenter-xShift)*acoef+ccoef);
                int intY=(int)((yCenter-zShift)*vcoef+wcoef);
                int intRx=(int)(c.getRadius()*acoef);
                int intRy=(int)(c.getRadius()*vcoef);
               
               
                primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
               
                /*
                primeIP.moveTo(intX,intY);
                primeIP.drawString(c.getMyOrder()+"");
                */
               
                String s="torus{"+c.getRadius()+",InternRad texture{T0} finish{F0}\n";
                s+=" rotate "+rot+"*180/pi*k*x ";  
                s+="translate <"+c.getCenter().getReal()+",0,"+c.getCenter().getIm()+">}\n";
                //s+="torus{"+c.getRadius()+",InternRad2 texture{T1} finish{F1}\n";
                //s+=" rotate "+rot+"*90/pi*k*x  rotate 180*z ";  
                //s+="translate <"+c.getCenter().getReal()+",0,"+c.getCenter().getIm()+">}";
                System.out.println(s);
                output.println(s);
                blenderOutput.println(c.getRadius()+" "+c.getCenter().getReal()+" "+c.getCenter().getIm()+" "+rot);
       
        }
       
        private void drawPoint(Complexe c){
                double xCenter=c.getReal();
                double yCenter=c.getIm();
                int intX=(int)(xCenter*acoef+ccoef);
                int intY=(int)(yCenter*vcoef+wcoef);
                primeIP.fillOval(intX-10,intY-10,20,20);
        }
       
       
       
       
       
        private void drawLine(double xd,double yd,double xf,double yf){
                int XD=(int)(xd*acoef+ccoef);
                int YD=(int)(yd*vcoef+wcoef);
                int XF=(int)(xf*acoef+ccoef);
                int YF=(int)(yf*vcoef+wcoef);
                primeIP.drawLine(XD,YD,XF,YF);
        }
       
       
               
       
       
       
       
        public void run(String arg) {
                primeIP = new ColorProcessor(X,Y);
               
               
                double limit=5;
       
                setBounds(-limit,limit,-limit,limit);
                setCoefs();
               
               
               
               
               
               
                Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
                primeIP.setColor(Color.BLACK);
               
                primeIP.fillPolygon(background);
               
               
                primeIP.setFont(new Font(null,Font.ITALIC,60));
                primeIP.setColor(Color.WHITE);
                primeIP.setLineWidth(5);

                try{
                        output=new PrintStream("/tmp/AmishVersionTravail.txt");
                        blenderOutput=new PrintStream("/tmp/AmishBlenderVersionTravail.txt");
                        /*
                        output=new PrintStream("C:/users/decomite/pictures/povray/cardioid.txt");
                        blenderOutput=new PrintStream("C:/users/decomite/pictures/povray/cardioidBlender.txt");
                        */
                }
                catch(Exception e){System.out.println("erreur "+e); System.exit(0); }
               
                setProcessor("Verifying", primeIP);
                
                
                int subdiv=150;
               
              

                for(int i=0;i<subdiv;i++){
                	  Complexe z=Complexe.createComplexeFromPolar(1,i*2*Math.PI/subdiv);
                	 
                     
                        //drawCircle(new Circle(z,Complexe.distance(z,Complexe.UN)),signe*Math.PI*Math.sqrt(((j+0.0)/subdiv)));
                        drawCircle(new Circle(z,Complexe.distance(z,Complexe.UN)),2*i*Math.PI/subdiv);
                        
                }
               
                show();
                System.out.println("done "); 
                
        }}
               
                //drawLine(x0,0,x1,0);
                //drawLine(0,y0,0,y1);
               
                //drawCircle(new Circle(Complexe.ZERO,1));
                //  pitch en (1,0)
                /*
                int subdiv=50;
                int j;
                int signe=1;
                for(int i=0;i<subdiv;i++){
                        Complexe z=Complexe.createComplexeFromPolar(1,i*2*Math.PI/subdiv);
                        j=i;
                        //if(i<=subdiv/2) {j=i; signe=1;} else {j=(subdiv-i);signe=-1;}
                        drawCircle(new Circle(z,Complexe.distance(z,Complexe.UN)),signe*Math.PI*Math.pow((j+0.0)/subdiv,1.0/3));
                }
               
                show();
                System.out.println("done ");
        }      
}*/
        